package com.yaodian100.ec.payment.service.impl;

import java.io.File;
import java.io.Serializable;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.betwixt.io.BeanWriter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;

import com.yaodian100.core.batch.service.BatchJobService;
import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.DomainService;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.DateUtil;
import com.yaodian100.core.common.utils.ServerValue;
import com.yaodian100.core.logger.service.LogService;
import com.yaodian100.core.mail.entity.Mail;
import com.yaodian100.core.mail.service.MailService;
import com.yaodian100.core.menu.entity.Menu;
import com.yaodian100.core.template.service.TemplateService;
import com.yaodian100.ec.member.entity.Member;
import com.yaodian100.ec.member.entity.VirtualBalance;
import com.yaodian100.ec.member.service.MemberService;
import com.yaodian100.ec.order.entity.Orders;
import com.yaodian100.ec.order.service.OrderService;
import com.yaodian100.ec.payment.entity.ApplyCashOut;
import com.yaodian100.ec.payment.entity.ApplyClaim;
import com.yaodian100.ec.payment.entity.BankTransfer;
import com.yaodian100.ec.payment.entity.BonusTransfer;
import com.yaodian100.ec.payment.entity.ThirdPartyTransfer;
import com.yaodian100.ec.payment.entity.TransferLog;
import com.yaodian100.ec.payment.service.TransferService;

public class TransferServiceImpl extends DomainServiceImpl<ThirdPartyTransfer> implements TransferService {
	private static Logger LOGGER = LoggerFactory.getLogger(TransferServiceImpl.class);
	private MemberService memberService;
	private DomainService<Menu> menuService;
	private OrderService orderService;
	private TemplateService velocityService;
	private MailService mailService;
	private ObjectDao<BonusTransfer> bonusTransferDao;
	private ObjectDao<BankTransfer> bankTransferDao;
	private ObjectDao<ApplyClaim> applyClaimDao;
	private ObjectDao<ApplyCashOut> applyCashOutDao;
	@Resource
	private BatchJobService batchJobService;
	@Resource
	private LogService logService;

	private ObjectDao<TransferLog> transferLogDao;
	private String mailFrom;

	/**
	 * 逾期應該也要直接轉招領
	 */
	@Transactional(readOnly = false)
	public boolean bathChargeByBankTransfer() throws CoreException {
		CommonCriteria crit = new CommonCriteria();
		crit.addEq("status", "10");
		// crit.addNe("orderId", null);
		List<BankTransfer> bankList = bankTransferDao.getListPageable(crit, null, 0, -1);
		if (!bankList.isEmpty()) {
			Iterator<BankTransfer> iter = bankList.iterator();
			while (iter.hasNext()) {
				BankTransfer bt = iter.next();
				boolean isCharged = false;
				if (StringUtils.isNotBlank(bt.getOrderId())) { // 若订单编号为空白,直接异动为召领
					Orders order = orderService.get(bt.getOrderId());
					try {
						if (null == order) {
							bt.setStatus("50");
						} else if (!"10".equals(order.getOrderSt())) {
							bt.setStatus("50");
						} else if (!"10".equals(order.getPaymentTp()) && !"20".equals(order.getPaymentTp())) {
							bt.setStatus("50");
						} else if (orderService.charge(bt.getOrderId(), bt.getId(), bt.getAmount())) {
							bt.setStatus("90");
							isCharged = true;
						} else {
							bt.setStatus("30");
						}

					} catch (Exception e) {
						bt.setStatus("30");
					}
				} else {
					bt.setStatus("50");
				}
				if (isCharged) {
					sendBankTransferResault(isCharged, bt);
				} else {
					sendBankTransferResault(isCharged, bt);
				}
			}
		}
		bankTransferDao.saveOrUpdateBatch(bankList);
		return true;
	}

	@Transactional(readOnly = false)
	public boolean chargeByBankTransfer(String orderId, String bankTransferId) throws CoreException {
		BankTransfer bankTransfer = bankTransferDao.get(bankTransferId);
		if (bankTransfer == null) {
			throw new CoreException("查无此转帐资料");
		}
		Orders order = orderService.get(orderId);
		if (order == null) {
			throw new CoreException("查无此订单资料");
		}

		// 状态：30（无法自动辨视）50（人工辨视失败,待招领），该笔交易单据订单编号需要为空白
		if (("30".equals(bankTransfer.getStatus()) || "50".equals(bankTransfer.getStatus()))
				&& StringUtils.isBlank(bankTransfer.getOrderId())) {
			bankTransfer.setStatus("10");
			bankTransfer.setOrderId(orderId);
			bankTransferDao.update(bankTransfer);
			logService.save(this.getClass().getName(), "chargeByBankTransfer", bankTransfer);
			// orderService.charge(orderId, bankTransferId, bankTransfer.getAmount());
		} else {
			throw new CoreException("此交易已转订单，无法再收款");
		}
		return true;
	}

	public void sendBankTransferResault(boolean isCharged, BankTransfer bankTransfer) {
		String tranferId = bankTransfer.getId();
		String orderId = bankTransfer.getOrderId();
		String amount = bankTransfer.getAmount().toString();
		String srcBank = bankTransfer.getSourceBank();
		String srcBankAccount = bankTransfer.getSourceAccountNo();
		String srcAccountHolder = bankTransfer.getSourceAccountName();
		String subject = "";
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:ms:ss");
		StringBuffer sb = new StringBuffer();
		sb.append("汇款记录编号 ：").append(tranferId).append("<br>");
		sb.append("订单编号 ：").append(orderId).append("<br>");
		sb.append("汇款资讯 ：").append("<br>");
		sb.append("汇款金额 ：").append(amount).append("<br>");
		sb.append("汇款银行 ：").append(srcBank).append("<br>");
		sb.append("汇款账号 ：").append(srcBankAccount).append("<br>");
		sb.append("汇款人 ：").append(srcAccountHolder).append("<br>");
		sb.append("收款时间 ：").append(df.format(new Date())).append("<br>");

		if (isCharged) {
			subject = "批次汇款收款成功";

		} else {
			subject = "批次汇款收款失败";
		}
		Mail mail = new Mail(subject, sb.toString(), "finance@yaodian100.com", null);
		mailService.save(mail);

	}

	@Transactional(readOnly = false)
	public boolean chargeByBonusTransfer(Orders order) throws Exception {
		if (order.getBonus().intValue() > 0) {
			// 先将订单的bonus($)换算为会员积分
			BigDecimal bonusPrice = order.getBonus().multiply(order.getOrderBonusCampaign().getOffsetRate());
			ArrayList<String> ayBonus = memberService.getAvailableBonus(order.getMemberId(), bonusPrice);
			ArrayList<BonusTransfer> bonusList = new ArrayList<BonusTransfer>();
			for (String sBonus : ayBonus) {
				String[] sAytBonus = sBonus.split(",");
				BonusTransfer bonusTransfer = new BonusTransfer();
				bonusTransfer.setBonusId(Long.parseLong(sAytBonus[0]));
				bonusTransfer.setOrderId(order.getOrderId());
				bonusTransfer.setUseBonus(new BigDecimal(sAytBonus[2]));
				bonusTransfer.setMemberId(order.getMemberId());
				bonusTransfer.setExpireDate(DateUtil.convertStringToDate(sAytBonus[1]));
				bonusTransfer.setRate(new BigDecimal(1));
				bonusTransfer.setRefoundBonus(new BigDecimal(0));
				bonusList.add(bonusTransfer);
			}
			bonusTransferDao.saveOrUpdateBatch(bonusList);
		}
		return true;
	}

	@Transactional(readOnly = false)
	public boolean chargeByThirdPartyTransfer(String thirdPartyId, String tid, String result) throws CoreException {
		// ThirdPartyTransfer thirdPartyTransfer = this.get(thirdPartyId);
		// thirdPartyTransfer.setResult(result);
		// thirdPartyTransfer.setTid(tid);
		// thirdPartyTransfer.setStatus("20");
		// thirdPartyTransfer.setTradeEndDt(new Date());
		// if (thirdPartyTransfer.getResult().equals("0000")) {
		// orderService.charge(thirdPartyTransfer.getOrderId(), thirdPartyId, thirdPartyTransfer.getAmount());
		// }
		// 第三方收款的相關功能，改為使用ThirdpartyPaymentService
		return true;
	}

	@Override
	public String checkOverOneThousandBonus(String memberId) throws Exception {
		CommonCriteria crit = new CommonCriteria();
		crit.addEq("memberId", memberId);
		crit.addGe("createDate", DateUtils.parseDate(FastDateFormat.getInstance("yyyy/MM/dd 00:00:00").format(new Date())
				.toString(), new String[] { "yyyy/MM/dd 00:00:00" }));
		List<BonusTransfer> bonusTransferList = bonusTransferDao.getListPageable(crit, null, 0, -1);
		BigDecimal sumTodayBonus = new BigDecimal(0);
		for (BonusTransfer bonusTransfer : bonusTransferList) {
			sumTodayBonus = sumTodayBonus.add(bonusTransfer.getUseBonus());
		}
		if (sumTodayBonus.intValue() > 1000) {
			return "Y";
		} else {
			return "N";
		}
	}

	// ========================= ApplyCashOut ===============================
	@Override
	public ApplyCashOut getApplyCashOut(String id) throws CoreException {
		ApplyCashOut applyCashOut = applyCashOutDao.get(id);
		return applyCashOut;
	}

	public ObjectDao<ApplyCashOut> getApplyCashOutDao() {
		return applyCashOutDao;
	}

	@Override
	public List<ApplyCashOut> getApplyCashOutList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		if (sortOrder == null) {
			return applyCashOutDao.getListPageable(criteria, null, firstResult, maxResults);
		}
		return applyCashOutDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.payment.service.TransferService#getApplyCashOutListSize(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */
	@Override
	public Number getApplyCashOutListSize(CommonCriteria criteria) throws CoreException {
		return applyCashOutDao.getListSize(criteria);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.payment.service.TransferService#getApplyClaim(java.io.Serializable)
	 */
	@Override
	public ApplyClaim getApplyClaim(Serializable id) throws CoreException {
		return applyClaimDao.get(id);
	}

	public ObjectDao<ApplyClaim> getApplyClaimDao() {
		return applyClaimDao;
	}

	// ========================= ApplyClaim ===============================
	@Override
	public List<ApplyClaim> getApplyClaimList(int firstResult, int maxResults, CommonCriteria criteria, String[] sortOrder)
			throws CoreException {
		if (sortOrder == null) {
			return applyClaimDao.getListPageable(criteria, null, firstResult, maxResults);
		}
		return applyClaimDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	@Override
	public Number getApplyClaimListSize(CommonCriteria criteria) throws CoreException {
		return applyClaimDao.getListSize(criteria);
	}

	public BankTransfer getBankTransfer(String oid) throws CoreException {
		return bankTransferDao.get(oid);
	}

	public ObjectDao<BankTransfer> getBankTransferDao() {
		return bankTransferDao;
	}

	@Override
	public List<BankTransfer> getBankTransferList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		String[] defaultSort = new String[] { "id" };
		if (sortOrder == null) {
			return bankTransferDao.getListPageable(criteria, defaultSort, firstResult, maxResults);
		}
		return bankTransferDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	public Number getBankTransferListSize(CommonCriteria criteria) throws CoreException {
		return bankTransferDao.getListSize(criteria);
	}

	public BonusTransfer getBonusTransfer(String oid) throws CoreException {
		return bonusTransferDao.get(oid);
	}

	public ObjectDao<BonusTransfer> getBonusTransferDao() {
		return bonusTransferDao;
	}

	@Override
	public List<BonusTransfer> getBonusTransferList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		// String[] defaultSort = new String[] { "orderId", "prodSeq" };
		if (sortOrder == null) {
			return bonusTransferDao.getListPageable(criteria, null, firstResult, maxResults);
		}
		return bonusTransferDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	public Number getBonusTransferListSize(CommonCriteria criteria) throws CoreException {
		return bonusTransferDao.getListSize(criteria);
	}

	public MemberService getMemberService() {
		return memberService;
	}

	public OrderService getOrderService() {
		return orderService;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean refoundBonusTransfer(String orderId, BigDecimal refoundBonus) throws Exception {
		String[] defaultSort = new String[] { "expireDate" };
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("orderId", orderId);
		criteria.addGe("useBonus - refoundBonus", new BigDecimal("0.00").setScale(2));
		List<BonusTransfer> bt = getBonusTransferList(0, -1, criteria, defaultSort);
		ArrayList<Map> btRefarr = new ArrayList();
		ArrayList btarr = new ArrayList();
		if (bt.size() > 0) {
			Orders order = orderService.get(orderId);
			BigDecimal bonusRate = order.getOrderBonusCampaign().getOffsetRate();
			Iterator iter = bt.iterator();
			while (iter.hasNext()) {
				BonusTransfer sBonus = (BonusTransfer) iter.next();
				Map btRef = new HashMap();
				// LOGGER.info("Bonus id:"+sBonus.getBonusId()+",UseBonus:{}"+ sBonus.getUseBonus());
				// LOGGER.info("Refound:{},Bonus-Refound:{}", sBonus.getRefoundBonus(), sBonus.getUseBonus().subtract(
				// sBonus.getRefoundBonus()).setScale(2));
				// LOGGER.info("Bonus-Refound-refound:{}", sBonus.getUseBonus().subtract(
				// sBonus.getRefoundBonus()).subtract(refoundBonus).setScale(2));
				// LOGGER.info("Bonus comareTo:{}", sBonus.getUseBonus().subtract(sBonus.getRefoundBonus())
				// .subtract(refoundBonus).setScale(2).compareTo(new BigDecimal("0.00").setScale(2)));
				refoundBonus = refoundBonus.multiply(bonusRate).setScale(0, RoundingMode.DOWN);
				if (sBonus.getUseBonus().subtract(sBonus.getRefoundBonus()).subtract(refoundBonus).setScale(0,
						RoundingMode.DOWN).compareTo(BigDecimal.ZERO) >= 0) { // 是否超过可退上限
					sBonus.setRefoundBonus((sBonus.getRefoundBonus().add(refoundBonus)));
					btRef.put(sBonus.getBonusId(), refoundBonus);
					btRefarr.add(btRef);
					btarr.add(sBonus);
					break;
				} else {
					BigDecimal tpRef = sBonus.getUseBonus().subtract(sBonus.getRefoundBonus()).setScale(0, RoundingMode.DOWN); // 单笔可退上限
					sBonus.setRefoundBonus((sBonus.getRefoundBonus().add(tpRef)));
					refoundBonus = refoundBonus.subtract(tpRef);
					btRef.put(sBonus.getBonusId(), tpRef);
					btRefarr.add(btRef);
					btarr.add(sBonus);
				}
			}
		}
		memberService.returnBonus(btRefarr, orderId);
		bonusTransferDao.saveOrUpdateBatch(btarr);
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public ApplyCashOut saveApplyCashOut(ApplyCashOut applyCashOut) throws CoreException {
		try {
			applyCashOut.setApplyDate(DateUtil.getToday().getTime());// 申请提现日期
			applyCashOut = applyCashOutDao.save(applyCashOut);
			// insert一笔扣款的账户余额
			VirtualBalance virtualBalance = new VirtualBalance();
			virtualBalance.setMemberId(applyCashOut.getMemberId());
			virtualBalance.setTrxAmount(applyCashOut.getApplyAmount().negate());
			virtualBalance.setTrxDate(applyCashOut.getApplyDate());
			virtualBalance.setTrxType("EC_APPLY_CASH_OUT");
			virtualBalance.setTrxTypeId(applyCashOut.getId());
			virtualBalance.setDescription("提现单号：" + applyCashOut.getId() + " "
					+ (applyCashOut.getCashOutType().equals("1") ? "(邮局汇款)" : "(银行转账)"));
			memberService.saveOrUpdateVirtualBalance(virtualBalance);

			// 寄送提现成功通知信
			Member member = memberService.get(applyCashOut.getMemberId());
			if (StringUtils.isNotBlank(member.getEmail())) {
				Map<String, Object> contentMap = new HashMap<String, Object>();
				contentMap.put("applyCashOut", applyCashOut);
				contentMap.put("loginId", member.getLoginId());
				contentMap.put("basehref", "http://" + member.getDomainSrc());
				contentMap.put("contextpath", ServerValue.getFrontContextPath());
				contentMap.put("virtualBalance", member.getBalance().getVirtualBalance());
				contentMap.put("domainSrc", member.getDomainSrc());
				Mail mail = null;
				if (applyCashOut.getCashOutType().equals("1")) {
					mail = velocityService.formatToMail("member.applyCashOutSuccessMail", contentMap);
				} else {
					contentMap.put("bankName", addMask1(applyCashOut.getReceiverBankName()));
					String number = applyCashOut.getReceiverBankAccountNumber();
					contentMap.put("bankAccountNumber", StringUtils.substring(number, 0, number.length() - 5) + "*****");
					mail = velocityService.formatToMail("member.applyCashOutBankSuccessMail", contentMap);
				}
				mail.setFrom(mailFrom);
				mail.setTo(member.getEmail());
				mailService.save(mail);
			}
			logService.save(this.getClass().getName(), "saveApplyCashOut", virtualBalance);
			// 提現同步
			batchJobService.save("EC-ApplyCashOutSyncJob", toXML(applyCashOut), null, applyCashOut.getMemberId());
		} catch (Exception e) {
			throw new CoreException("提现新增失败");
		}
		return applyCashOut;
	}

	@Transactional(readOnly = false)
	public ApplyClaim saveApplyClaim(ApplyClaim applyClaim, byte[] fileBody) throws CoreException {
		try {
			applyClaim.setApplyDate(new Date());// 申请提现日期
			applyClaim = applyClaimDao.save(applyClaim);
			// upload img file
			StringBuilder imgFilePath = new StringBuilder();
			imgFilePath.append(ServerValue.getMidApachePath()).append("claimImg").append(File.separator).append(
					applyClaim.getId()).append(applyClaim.getImgSubName());
			File file = new File(imgFilePath.toString());
			FileCopyUtils.copy(fileBody, file);

			// 寄送招领成功通知信
			Map<String, Object> contentMap = new HashMap<String, Object>();
			Member member = memberService.get(applyClaim.getMemberId());
			contentMap.put("loginId", member.getLoginId());
			contentMap.put("applyClaim", applyClaim);
			contentMap.put("contactPhone", addMask(applyClaim.getContactPhone()));
			contentMap.put("contactEmail", addMask(applyClaim.getContactEmail()));
			contentMap.put("basehref", "http://" + member.getDomainSrc());
			contentMap.put("contextpath", ServerValue.getFrontContextPath());
			contentMap.put("claimTypeMenu", menuService.get("ApplyClaim.ClaimType"));
			contentMap.put("domainSrc", member.getDomainSrc());
			Mail mail = velocityService.formatToMail("member.applyClaimSuccessMail", contentMap);
			mail.setTo(applyClaim.getContactEmail());
			mail.setFrom(mailFrom);
			mailService.save(mail);

			if (!applyClaim.getContactEmail().equals(member.getSendEmail())) {
				mail = velocityService.formatToMail("member.applyClaimSuccessMail", contentMap);
				mail.setTo(member.getSendEmail());
				mail.setFrom(mailFrom);
				mailService.save(mail);
			}

			logService.save(this.getClass().getName(), "saveApplyClaim", applyClaim);
		} catch (Exception e) {
			e.printStackTrace();
			throw new CoreException("招领单新增失败", e);
		}
		return applyClaim;
	}

	@Transactional(readOnly = false)
	public void saveBankTransfer(BankTransfer bankTransfer) throws CoreException {
		bankTransfer = bankTransferDao.save(bankTransfer);
		// 匯款資訊
		logService.save(this.getClass().getName(), "saveBankTransfer", bankTransfer);
		batchJobService.save("EC-BankTransferJob", toXML(bankTransfer), null, bankTransfer.getOrderId());

	}

	@Transactional(readOnly = false)
	public void saveBonusTransfer(BonusTransfer bonusTransfer) throws CoreException {
		bonusTransferDao.save(bonusTransfer);
	}

	void sendApplyClaimMail(String velocityTemplate, ApplyClaim applyClaim) throws CoreException {
		applyClaim = updateApplyClaim(applyClaim);
		Member member = memberService.get(applyClaim.getMemberId());
		Map<String, Object> contentMap = new HashMap<String, Object>();
		contentMap.put("loginId", member.getLoginId());
		contentMap.put("applyClaim", applyClaim);
		contentMap.put("basehref", "http://" + member.getDomainSrc());
		contentMap.put("contextpath", ServerValue.getFrontContextPath());
		contentMap.put("customerFax", ServerValue.getCustomerFax());
		contentMap.put("customerTel", ServerValue.getCustomerTel());
		contentMap.put("domainSrc", member.getDomainSrc());
		Mail mail = velocityService.formatToMail(velocityTemplate, contentMap);
		mail.setTo(applyClaim.getContactEmail());
		mail.setFrom(mailFrom);
		mailService.save(mail);

		if (!applyClaim.getContactEmail().equals(member.getSendEmail())) {
			mail = velocityService.formatToMail(velocityTemplate, contentMap);
			mail.setTo(member.getSendEmail());
			mail.setFrom(mailFrom);
			mailService.save(mail);
		}
	}

	public void setApplyCashOutDao(ObjectDao<ApplyCashOut> applyCashOutDao) {
		this.applyCashOutDao = applyCashOutDao;
	}

	public void setApplyClaimDao(ObjectDao<ApplyClaim> applyClaimDao) {
		this.applyClaimDao = applyClaimDao;
	}

	public void setBankTransferDao(ObjectDao<BankTransfer> bankTransferDao) {
		this.bankTransferDao = bankTransferDao;
	}

	public void setBonusTransferDao(ObjectDao<BonusTransfer> bonusTransferDao) {
		this.bonusTransferDao = bonusTransferDao;
	}

	public void setMailFrom(String mailFrom) {
		this.mailFrom = mailFrom;
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}

	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}

	public void setMenuService(DomainService<Menu> menuService) {
		this.menuService = menuService;
	}

	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;
	}

	public void setVelocityService(TemplateService velocityService) {
		this.velocityService = velocityService;
	}

	private String toXML(Object entity) {
		String xml = null;
		try {

			StringWriter sw = new StringWriter();
			BeanWriter beanWriter = new BeanWriter(sw);
			beanWriter.enablePrettyPrint();
			beanWriter.getBindingConfiguration().setMapIDs(false);
			beanWriter.write(entity);
			xml = sw.toString();
			beanWriter.flush();
			beanWriter.close();
		} catch (Exception e) {
			logger.info("to XML Exception:{}", e);

		}
		return xml;

	}

	@Override
	@Transactional(readOnly = false)
	public ApplyCashOut updateApplyCashOut(ApplyCashOut erpApplyCashOut) throws CoreException {
		ApplyCashOut ecApplyCashOut = applyCashOutDao.get(erpApplyCashOut.getId());
		try {

			ecApplyCashOut.setCashOutStatus(erpApplyCashOut.getCashOutStatus());
			ecApplyCashOut.setApplyDate(erpApplyCashOut.getApplyDate());
			if (StringUtils.isNotEmpty(erpApplyCashOut.getCashOutMemo())) {
				ecApplyCashOut.setCashOutMemo(erpApplyCashOut.getCashOutMemo());
			}

			Member member = memberService.get(ecApplyCashOut.getMemberId());
			if ("80".equals(ecApplyCashOut.getCashOutStatus())) {// 提領成功
				ecApplyCashOut.setApproveDate(new Date());
				memberService.updateVirtualBalanceDate(ecApplyCashOut.getId(), member.getMemberId(), ecApplyCashOut
						.getApproveDate());
				// 寄送提现成功通知信
				Map<String, Object> contentMap = new HashMap<String, Object>();
				contentMap.put("applyCashOut", ecApplyCashOut);
				contentMap.put("loginId", member.getLoginId());
				contentMap.put("basehref", "http://" + member.getDomainSrc());
				contentMap.put("contextpath", ServerValue.getFrontContextPath());
				contentMap.put("virtualBalance", member.getBalance().getVirtualBalance());
				contentMap.put("domainSrc", member.getDomainSrc());
				if (ecApplyCashOut.getCashOutType().equals("2")) {
					contentMap.put("bankName", addMask1(ecApplyCashOut.getReceiverBankName()));
					String number = ecApplyCashOut.getReceiverBankAccountNumber();
					contentMap.put("bankAccountNumber", StringUtils.substring(number, 0, number.length() - 5) + "*****");
				}
				Mail mail = velocityService.formatToMail("member.applyCashOutApproveMail", contentMap);
				mail.setTo(member.getEmail());
				mail.setFrom(mailFrom);
				mailService.save(mail);

			} else if ("90".equals(ecApplyCashOut.getCashOutStatus())) {// 提領失敗

				try {
					// 預防多筆寫入
					TransferLog transferLog = new TransferLog();
					transferLog.setId(ecApplyCashOut.getId());
					transferLogDao.save(transferLog);
					// insert一笔還款到账户余额
					VirtualBalance virtualBalance = new VirtualBalance();
					virtualBalance.setMemberId(ecApplyCashOut.getMemberId());
					virtualBalance.setTrxAmount(ecApplyCashOut.getApplyAmount());
					virtualBalance.setTrxDate(ecApplyCashOut.getApplyDate());
					virtualBalance.setTrxType("EC_APPLY_CASH_OUT");
					virtualBalance.setTrxTypeId(ecApplyCashOut.getId());
					virtualBalance.setDescription("提现失败存回，提现单号：" + ecApplyCashOut.getId());
					memberService.saveOrUpdateVirtualBalance(virtualBalance);
					// 寄送提现失败通知信
					Map<String, Object> contentMap = new HashMap<String, Object>();
					if (!StringUtils.isNotEmpty(erpApplyCashOut.getCashOutMemo())) {
						ecApplyCashOut.setCashOutMemo("");
					}
					contentMap.put("applyCashOut", ecApplyCashOut);
					contentMap.put("loginId", member.getLoginId());
					contentMap.put("basehref", "http://" + member.getDomainSrc());
					contentMap.put("contextpath", ServerValue.getFrontContextPath());
					contentMap.put("domainSrc", member.getDomainSrc());
					Mail mail = velocityService.formatToMail("member.applyCashOutFailureMail", contentMap);
					mail.setTo(member.getEmail());
					mail.setFrom(mailFrom);
					mailService.save(mail);
				} catch (Exception e) {
					logger.error(e.getMessage());
					throw new CoreException("提现失败，存回失败");
				}

			}
			ecApplyCashOut = applyCashOutDao.update(ecApplyCashOut);
			logService.save(this.getClass().getName(), "updateApplyCashOut", ecApplyCashOut);
		} catch (Exception e) {
			e.printStackTrace();
			throw new CoreException("提现修改失败");
		}
		return ecApplyCashOut;
	}

	@Override
	@Transactional(readOnly = false)
	public ApplyClaim updateApplyClaim(ApplyClaim applyClaim) throws CoreException {
		try {
			applyClaim = applyClaimDao.update(applyClaim);
			logService.save(this.getClass().getName(), "updateApplyClaim", applyClaim);
		} catch (Exception e) {
			throw new CoreException("招领单修改失败");
		}
		return applyClaim;
	}

	@Transactional(readOnly = false)
	public String updateApplyClaimStatus(ApplyClaim applyClaim) throws CoreException {
		try {
			if (StringUtils.equals("90", applyClaim.getClaimStatus())) {// 中台比对资料不符合
				applyClaim.setClaimStatus("90");// 招领失败
				applyClaim.setClaimReason(applyClaim.getClaimReason());
				applyClaim.setReviewDate(new Date());
				sendApplyClaimMail("applyClaim.applyClaimFailureMail", applyClaim);
			} else if (StringUtils.equals("20", applyClaim.getClaimStatus())) {// 退费作业
				applyClaim.setClaimStatus("60");// 退费成功

				BankTransfer bankTransfer = bankTransferDao.get(applyClaim.getBankTransferId());
				if (null != bankTransfer) {
					// 更新banktransfer 状态[70 已退款]
					bankTransfer.setStatus("70");
					bankTransfer = bankTransferDao.update(bankTransfer);
					logService.save(this.getClass().getName(), "updateApplyClaimStatus", bankTransfer);
					// banktransfer 同步至后台
					batchJobService.save("EC-BankTransferUpdateJob", toXML(bankTransfer), null, bankTransfer.getOrderId());

					// member virtual balance新增
					// if ("2".equals(applyClaim.getClaimType())) {
					sendApplyClaimMail("applyClaim.applyClaimMyBalanceSuccessMail", applyClaim);
					VirtualBalance virtualBalance = new VirtualBalance();
					virtualBalance.setApproveDate(new Date());
					applyClaim.setReviewDate(virtualBalance.getApproveDate());
					virtualBalance.setMemberId(applyClaim.getMemberId());
					virtualBalance.setTrxAmount(bankTransfer.getAmount());
					virtualBalance.setTrxDate(new Date());
					virtualBalance.setTrxType("EC_APPLY_CLAIM");
					virtualBalance.setTrxTypeId(applyClaim.getId());
					virtualBalance.setDescription("汇款认领退还 （订单编号：" + "<a href=\"" + ServerValue.getFrontContextPath()
							+ "/member/order/page.do?page=detail&orderId=" + applyClaim.getOrderId() + "\">"
							+ applyClaim.getOrderId() + "</a>）");
					memberService.saveOrUpdateVirtualBalance(virtualBalance);

					// }
					applyClaim.setReviewDate(new Date());
					applyClaim = updateApplyClaim(applyClaim);
					logService.save(this.getClass().getName(), "updateApplyClaimStatus", applyClaim);
				}

			} else {
				BankTransfer bankTransfer = getBankTransfer(applyClaim.getBankTransferId());
				// 招領金額與招領單號上的金額相符
				if (null != bankTransfer && bankTransfer.getAmount().compareTo(applyClaim.getClaimAmount()) == 0) {
					if (chargeByBankTransfer(applyClaim.getOrderId(), applyClaim.getBankTransferId())) {
						applyClaim.setClaimStatus("70");// 招领成功
						applyClaim.setReviewDate(new Date());
						if ("1".equals(applyClaim.getClaimType())) {
							sendApplyClaimMail("applyClaim.applyClaimPayOrderSuccessMail", applyClaim);
						}
					}
				} else {
					applyClaim.setReviewDate(new Date());
					applyClaim.setClaimStatus("90");// 招领失败
					applyClaim.setClaimReason("招领资料比对不符");
					sendApplyClaimMail("applyClaim.applyClaimFailureMail", applyClaim);
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
			applyClaim.setClaimStatus("90");// 招领失败
			applyClaim.setClaimReason("招领资料比对不符");
			sendApplyClaimMail("applyClaim.applyClaimFailureMail", applyClaim);
		}
		return applyClaim.getClaimStatus();
	}

	@Transactional(readOnly = false)
	public void updateBankTransfer(BankTransfer bankTransfer) throws CoreException {
		bankTransferDao.update(bankTransfer);
		logService.save(this.getClass().getName(), "updateBankTransfer", bankTransfer);
	}

	@Transactional(readOnly = false)
	public String updateBankTransferList(String[] bankIdList, String status) throws CoreException {
		StringBuffer sb = new StringBuffer();
		if (bankIdList != null) {
			for (int i = 0; i < bankIdList.length; i++) {
				BankTransfer bk = this.getBankTransfer(bankIdList[i]);
				if (bk.getStatus().equals("10") || bk.getStatus().equals("30")) {
					bk.setStatus(status);
					bankTransferDao.update(bk);
					sb.append(bankIdList[i]).append(":储存成功");
					logService.save(this.getClass().getName(), "updateBankTransferList", bk);
				} else {
					sb.append(bankIdList[i]).append(":目前状态不可以异动");
				}
			}
		} else {
			sb.append("传入空资料,无法更新");
		}
		return sb.toString();
	}

	@Transactional(readOnly = false)
	public void updateBonusTransfer(BonusTransfer bonusTransfer) throws CoreException {
		bonusTransferDao.update(bonusTransfer);
	}

	private String addMask(String input) {
		StringBuffer sb = new StringBuffer();
		int start = input.length() / 3;
		for (int i = 0; i < start; i++) {
			sb.append("*");
		}
		return input.replace(input.substring(start, start * 2), sb.toString());
	}

	private String addMask1(String input) {
		StringBuffer sb = new StringBuffer();
		int start = input.lastIndexOf('-');
		for (int i = start + 1; i <= input.length() - 1; i++) {
			sb.append("*");
		}
		return StringUtils.substring(input, 0, input.lastIndexOf('-') + 1) + sb.toString();
	}

	public ObjectDao<TransferLog> getTransferLogDao() {
		return transferLogDao;
	}

	public void setTransferLogDao(ObjectDao<TransferLog> transferLogDao) {
		this.transferLogDao = transferLogDao;
	}
}